package org.sam.swing;

import java.awt.BorderLayout;
import java.text.NumberFormat;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.table.DefaultTableCellRenderer;

import org.jdesktop.swingx.JXTreeTable;
import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode;
import org.jdesktop.swingx.treetable.DefaultTreeTableModel;
import org.sam.swing.table.JSTableColumn;
import org.sam.swing.table.JSTableColumnModel;
import org.sam.swing.table.editor.JSTableSpinnerEditor;
import org.sam.swing.table.renderer.JSTableFormatRenderer;

/**
 * 树形表格示例
 * 
 * @author sam
 *
 */
public class JPanelTreeTableDemo extends JPanel {

	private static final long serialVersionUID = 2642453605792290753L;

	/**
	 * 树形表格示例
	 */
	public JPanelTreeTableDemo() {
		this.initCompent();
	}

	/**
	 * 初始化控件显示
	 */
	private void initCompent() {
		this.setLayout(new BorderLayout());
		DeptTreeTableModel treeModel = new DeptTreeTableModel("民航数据通信中心有限公司");
		treeModel.setOrginal(this.getData());
		JXTreeTable table = new JXTreeTable(treeModel);
		table.setColumnControlVisible(true);
		table.setColumnModel(this.getColumnModel());
		this.add(new JScrollPane(table), BorderLayout.CENTER);
	}

	/**
	 * 获取数据信息
	 * 
	 * @return
	 */
	private List<Dept> getData() {
		List<Dept> result = new LinkedList<>();
		for (int i = 0; i < 10; i++) {
			Dept dept = new Dept();
			dept.setCode("code" + i);
			dept.setName("name" + i);
			dept.setEmployees(new LinkedList<>());

			Dept subDept = new Dept();
			subDept.setCode("subcode" + i);
			subDept.setName("subname" + i);
			subDept.setEmployees(new LinkedList<>());

			dept.setSubDept(subDept);

			for (int j = 0; j < 15; j++) {
				TestEntity entity = new TestEntity();
				entity.setAge(j);
				entity.setCode("code:" + j);
				entity.setName("name:" + j);
				dept.getEmployees().add(entity);
			}
			result.add(dept);
		}
		return result;
	}

	/**
	 * 生成列编辑对象
	 * 
	 * @return
	 */
	private JSTableColumnModel getColumnModel() {

		JSTableColumnModel result = new JSTableColumnModel();

		DefaultTableCellRenderer renderl = new DefaultTableCellRenderer();

		// 整数格式的渲染器
		JSTableFormatRenderer integerRenderer = new JSTableFormatRenderer(NumberFormat.getIntegerInstance(), "");
		integerRenderer.setHorizontalAlignment(JSTableFormatRenderer.RIGHT);
		JSTableSpinnerEditor integerEditor = new JSTableSpinnerEditor(
				new JSpinner(new SpinnerNumberModel(0, 0, 100000, 100)));

		JSTableColumn c0 = new JSTableColumn();
		c0.setModelIndex(0);
		c0.setHeaderValue("代码");
		c0.setTitle("代码");
		c0.setIdentifier("");
		c0.setMinWidth(120);
		c0.setDefaultValue("");
		c0.setCellRenderer(renderl);
		result.addColumn(c0);

		JSTableColumn c1 = new JSTableColumn();
		c1.setModelIndex(1);
		c1.setHeaderValue("代码");
		c1.setTitle("代码");
		c1.setIdentifier("code");
		c1.setMinWidth(120);
		c1.setDefaultValue("");
		c1.setCellRenderer(renderl);
		result.addColumn(c1);

		JSTableColumn c2 = new JSTableColumn();
		c2.setModelIndex(2);
		c2.setHeaderValue("名称");
		c2.setTitle("名称");
		c2.setIdentifier("name");
		c2.setMinWidth(150);
		c2.setCellRenderer(renderl);
		result.addColumn(c2);

		JSTableColumn c3 = new JSTableColumn();
		c3.setModelIndex(3);
		c3.setHeaderValue("年龄");
		c3.setTitle("年龄");
		c3.setIdentifier("age");
		c3.setMinWidth(90);
		c3.setDefaultValue(0);
		c3.setCellRenderer(integerRenderer);
		c3.setCellEditor(integerEditor);
		result.addColumn(c3);

		return result;
	}

	/**
	 * 部门信息
	 * 
	 * @author sam
	 *
	 */
	private class DeptTreeTableModel extends DefaultTreeTableModel {

		/**
		 * 原始数据
		 */
		private List<?> orginal;

		/**
		 * 原始数据
		 * 
		 * @return
		 */
		public List<?> getOrginal() {
			return orginal;
		}

		/**
		 * 需要带参数的构造函数
		 * 
		 * @param root
		 */
		private DeptTreeTableModel(Object root) {
			super(new DefaultMutableTreeTableNode(root));
			this.addTreeModelListener(new TreeModelListener() {

				@Override
				public void treeNodesChanged(TreeModelEvent e) {
					System.out.println("treeNodesChanged:");
					System.out.println(e);
				}

				@Override
				public void treeNodesInserted(TreeModelEvent e) {
					System.out.println("treeNodesInserted:");
					System.out.println(e);
				}

				@Override
				public void treeNodesRemoved(TreeModelEvent e) {
					System.out.println("treeNodesRemoved:");
					System.out.println(e);
				}

				@Override
				public void treeStructureChanged(TreeModelEvent e) {
					System.out.println("treeStructureChanged:");
					System.out.println(e);
				}
			});
		}

		/**
		 * 原始数据
		 * 
		 * @param orginal
		 */
		public void setOrginal(List<?> orginal) {
			this.orginal = orginal;
		}

		@Override
		public int getColumnCount() {
			return 4;
		}

		@Override
		public Object getValueAt(Object node, int column) {

			if (node instanceof Dept) {
				switch (column) {
				case 0:
					return ((Dept) node).getCode();
				default:
					return null;
				}

			} else if (node instanceof TestEntity) {
				switch (column) {
				case 0:
					return "";
				case 1:
					return ((TestEntity) node).getCode();
				case 2:
					return ((TestEntity) node).getName();
				case 3:
					return ((TestEntity) node).getAge();
				default:
					return null;
				}
			} else {
				return node.toString();
			}
		}

		@Override
		public Object getChild(Object parent, int index) {
			if (parent instanceof Dept) {
				if (index == 0) {
					if (((Dept) parent).getSubDept() != null)
						return ((Dept) parent).getSubDept();
					else
						return ((Dept) parent).getEmployees().get(index);
				} else {
					if (((Dept) parent).getSubDept() != null)
						return ((Dept) parent).getEmployees().get(index - 1);
					else
						return ((Dept) parent).getEmployees().get(index);
				}
			} else if (parent == this.getRoot()) {
				return this.getOrginal().get(index);
			} else {
				return null;
			}
		}

		@Override
		public int getChildCount(Object parent) {
			if (parent instanceof Dept) {
				Dept dept = (Dept) parent;
				if (dept.getSubDept() != null)
					return dept.getEmployees().size() + 1;

				return dept.getEmployees().size();
			} else if (parent == this.getRoot()) {
				return this.getOrginal().size();
			} else {
				return 0;
			}
		}

		@Override
		public int getIndexOfChild(Object parent, Object child) {
			if (parent instanceof Dept) {

				Dept dept = (Dept) parent;
				if (child instanceof Dept)
					return 0;

				int condition = (dept.getSubDept() == null ? 0 : 1);

				List<TestEntity> employees = dept.getEmployees();
				for (int i = 0; i < employees.size(); i++) {
					TestEntity entity = employees.get(i);
					if (Objects.equals(entity, child))
						return i + condition;
				}
			} else if (parent == this.getRoot()) {
				for (int i = 0; i < this.getOrginal().size(); i++) {
					Object object = this.getOrginal().get(i);
					if (Objects.equals(child, object))
						return i;
				}
			}

			return 0;
		}

		/**
		 * 那列可编辑
		 */
		@Override
		public boolean isCellEditable(Object node, int column) {
			if (node instanceof TestEntity) {
				return column > 0;
			}

			return false;
		}

		/**
		 * 是否是叶子节点
		 */
		@Override
		public boolean isLeaf(Object node) {
			return node instanceof TestEntity;
		}

		/**
		 * 设置值
		 */
		@Override
		public void setValueAt(Object value, Object node, int column) {
			if (node instanceof Dept) {
				switch (column) {
				case 0:
					((Dept) node).setCode(value.toString());
					break;
				}

			} else if (node instanceof TestEntity) {
				switch (column) {
				case 1:
					((TestEntity) node).setCode(value.toString());
					break;
				case 2:
					((TestEntity) node).setName(value.toString());
					break;
				case 3:
					((TestEntity) node).setAge(Integer.valueOf(value.toString()));
					break;
				}
			}
		}

	}
}
